package com.gitee.wsl.mathematics.matrix.mat3

import com.gitee.wsl.ext.array.DoubleArray
import com.gitee.wsl.ext.list.exactSize
import com.gitee.wsl.io.dataproxy.DataGet
import com.gitee.wsl.io.dataproxy.asProxy
import com.gitee.wsl.mathematics.matrix.M
import com.gitee.wsl.mathematics.matrix.N
import com.gitee.wsl.mathematics.matrix.mat2.Matrix2
import com.gitee.wsl.mathematics.matrix.mat2.MutableMat2
import com.gitee.wsl.mathematics.matrix.mat2.MutableMatrix2
import com.gitee.wsl.mathematics.vector.vec2.Vec2
import com.gitee.wsl.mathematics.vector.vec3.Vec3

open class Mat3(m00: Double=0.0, m01: Double=0.0,m02: Double=0.0,
                m10: Double=0.0, m11: Double=0.0,m12: Double=0.0,
                m20: Double=0.0, m21: Double=0.0,m22: Double=0.0,
                override val proxy: DataGet<Double> =
                    DoubleArray(
                        m00, m01, m02,
                        m10, m11, m12,
                        m20, m21, m22).asProxy())
    :Matrix3D<Mat3, Vec3> {

    override val self
        get() = this

    override val m by lazy{listOf(M[0], M[1],M[2])}

    override val n by lazy {listOf(N[0], N[1],N[2])}

    override fun createVec(indexes: List<Int>) = Vec3(proxy = proxy.asProxy(indexes))

    override fun createVec2(x: Double, y: Double) = Vec2(x,y)

    override fun createMat2(block: (MutableMatrix2<Double, *, *>) -> Unit): Matrix2<Double, *, *> {
        val ret = MutableMat2()
        block(ret)
        return ret
    }

    override fun create(m00: Double, m01: Double,m02: Double,
                        m10: Double, m11: Double,m12: Double,
                        m20: Double, m21: Double,m22: Double)
    =   Mat3(m00, m01, m02,
             m10, m11, m12,
             m20, m21, m22)

    override fun create(values: List<Double>): Mat3
    = Mat3(proxy = values.exactSize(9) { 0.0 }.toDoubleArray().asProxy())

    override fun toMutable() = MutableMat3(this)

    override fun hashCode(): Int =
        m00.hashCode() xor
                (m01.hashCode() xor 0x75A5A5A5) xor
                (m10.hashCode() xor 0x5A5A5A5A) xor
                (m11.hashCode() xor 0x76969696)

    override fun equals(other: Any?) =
        other is Mat3 &&
                m00 approx  other.m00 &&
                m01 approx other.m01 &&
                m10 approx other.m10 &&
                m11 approx other.m11

    override fun toString() = "(($m00, $m01),\n ($m10, $m11))"

}
